from moviepy.Clip import Clip
from moviepy.editor import *

from config import Config

__ERR_INFO = {
    "100": "源文件不存在",
    "200": 'LOGO文件不存在',
    "201": 'LOGO文件不符合要求',
    "300": '片头文件不存在',
    "301": '片头文件不符合要求',
    "400": '片尾文件不存在',
    "401": '片尾文件不符合要求',
}


def info(msg, prefix="Moviepy - "):
    print("{prefix}{msg}".format(prefix=prefix, msg=msg))


def isClip(ins):
    if bool(ins) and isinstance(ins, Clip):
        return True
    else:
        return False


def load_files():
    """
    加载源文件
    """
    data = []
    inputPath = Config.inputPath
    for root, subdir, files in os.walk(inputPath):
        for file in files:
            path = os.path.join(root, file)
            name, ext = os.path.splitext(path)
            if ext in Config.videoType:
                data.append(path)
    return data


def clean_files(files=None):
    if files is None:
        files = []
    if len(files) > 0:
        if Config.delConfirm:
            info('即将移除源文件,确认删除请按y,保留请按n')
            cmdStr = (input("Moviepy - ")).split(" ")[0]
            if cmdStr.lower() == 'y':
                info("源文件清除开始")
                for file in files:
                    os.remove(file)
                info("源文件清除完成")
        else:
            info("源文件清除开始")
            for file in files:
                os.remove(file)
            info("源文件清除完成")


def create_clip(file, clipType="image", duration=0):
    if not os.path.isabs(file):
        file = os.path.abspath(file)
    if not os.path.exists(file):
        info("注意：`{file}`不存在".format(file=file))
        return False
    if clipType == "image":
        if duration > 0:
            return ImageClip(file).set_duration(duration)
        else:
            return ImageClip(file)
    elif clipType == "video":
        videoClip = VideoFileClip(file)
        if 0 < duration < videoClip.duration:
            return videoClip.subclip(0, duration)
        else:
            return videoClip
    else:
        return False


def sub_clip(file):
    if os.path.exists(file):
        clip = VideoFileClip(file)
        duration = clip.duration
        start = Config.subClipStart
        end = Config.subClipEnd
        if (start + end) < duration:
            target = clip.subclip(start, duration - end)
            return target
        else:
            return clip
    else:
        return False


def load_logo_clip():
    """创建LOGO视频片段"""
    if Config.setLogoClip:
        logoClip = create_clip(Config.logoClipPath, Config.logoClipType)
        if isClip(logoClip):
            # 裁剪LOGO
            if (Config.logoClipWidth > 0 and Config.logoClipHeight > 0 and (
                    logoClip.w > Config.logoClipWidth or Config.logoClipHeight > logoClip.h)):
                return logoClip.resise((Config.logoClipWidth, Config.logoClipHeight))
            else:
                return logoClip
        else:
            return False
    else:
        return False


def load_start_clip():
    """创建视频片头"""
    if Config.setStartClip:
        startClip = create_clip(Config.startClipPath, Config.startClipType, Config.startClipDuration)
        return startClip
    else:
        return False


def load_end_clip():
    """创建视频结尾"""
    if Config.setEndClip:
        endClip = create_clip(Config.endClipPath, Config.endClipType, Config.endClipDuration)
        return endClip
    else:
        return False


def edit_clip(file, logo=False, start=False, end=False):
    """编辑视频"""
    if os.path.exists(file):
        # 创建主片段
        if Config.subClip:
            mainClip = sub_clip(file)
        else:
            mainClip = VideoFileClip(file)
        if not isClip(mainClip):
            return False
        mainDuration = mainClip.duration
        # 创建片头
        if isClip(start):
            startDuration = start.duration
            clips = [start.resize((mainClip.w, mainClip.h)), mainClip.set_start(startDuration)]
        else:
            startDuration = 0
            clips = [mainClip]
        midDuration = startDuration + mainDuration
        # 创建LOGO
        if isClip(logo):
            # 支持负数设置
            x = Config.logoClipPosX if Config.logoClipPosX >= 0 else mainClip.w - logo.w - abs(Config.logoClipPosX)
            y = Config.logoClipPosY if Config.logoClipPosY >= 0 else mainClip.h - logo.h - abs(Config.logoClipPosY)
            clips.append(logo.set_pos((x, y)).set_start(startDuration).set_end(midDuration))
        # 创建片尾
        if isClip(end):
            clips.append(end.resize((mainClip.w, mainClip.h)).set_start(midDuration))
        # 渲染视频
        output_file_path = Config.outputPath + "/" + os.path.basename(file)
        if len(clips) > 1:
            finalClip = CompositeVideoClip(clips)
            finalClip.write_videofile(output_file_path, fps=Config.fps, codec=Config.videoCodec,
                                      audio_codec=Config.audioCodec)
            finalClip.close()
            mainClip.close()
        else:
            mainClip.write_videofile(output_file_path, fps=Config.fps, codec=Config.videoCodec,
                                     audio_codec=Config.audioCodec)
            mainClip.close()
        return True
    else:
        return False


def main():
    files = load_files()
    num = len(files)
    if num > 0:
        info("待处理视频数:{num}".format(num=num))
        logo = load_logo_clip()
        start = load_start_clip()
        end = load_end_clip()
        suc = err = 0
        delFiles = []
        info("视频处理开始")
        for file in files:
            if edit_clip(file, logo, start, end):
                suc = suc + 1
                delFiles.append(file)
            else:
                err = err + 1
        # 关闭公用视频文件
        logo.close() if isClip(logo) else logo
        start.close() if isClip(start) else start
        end.close() if isClip(end) else end
        # 清除源文件
        clean_files(delFiles)
        info("视频处理完成，成功 {suc},失败 {err}".format(suc=suc, err=err))
    else:
        info("未发现可处理的视频")


def show_menu():
    info('命令菜单')
    info('1：批量编辑视频')
    info('i：初始化配置文件')
    info('r：重新加载配置文件')
    info('q：退出程序')


if __name__ == '__main__':
    info('程序启动')
    info('版本v1.0')
    while True:
        show_menu()
        info('请输入命令：')
        command = input("Moviepy - ")
        method = (command.split(" ")[0]).lower()
        if method == '1':
            main()
            continue
        elif method == 'q':
            info('程序退出，再见！')
            sys.exit()
        elif method == 'r':
            Config.reloadConfig()
            info('配置文件重新加载成功')
            continue
        elif method == 'i':
            info('注意：如果配置文件已存在，内容会被覆盖，请注意备份')
            info('确定要初始化配置文件吗？(y/n)')
            cmd = input("Moviepy - ")
            code = cmd.split(" ")[0]
            if code.lower() == 'y':
                Config.initConfig()
                Config.reloadConfig()
                info('配置文件初始化成功')
            continue
        else:
            info('非法命令，请重新输入')
            continue
